/*
 * 版权所有 (C) 2015 知启蒙(ZHIQIM) 保留所有权利。[遇见知启蒙，邂逅框架梦]
 * 
 * https://zhiqim.org/project/zhiqim_framework/zhiqim_httpd.htm
 *
 * Zhiqim Httpd is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *          http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */
package org.zhiqim.httpd.context;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;

import org.zhiqim.httpd.HttpContext;
import org.zhiqim.httpd.HttpExecutor;
import org.zhiqim.httpd.HttpRequest;
import org.zhiqim.httpd.HttpResponse;
import org.zhiqim.httpd.context.service.AjaxService;
import org.zhiqim.httpd.context.service.RmiService;
import org.zhiqim.httpd.context.service.UploadService;
import org.zhiqim.httpd.context.service.VcodeService;
import org.zhiqim.httpd.context.service.WebSocketService;
import org.zhiqim.kernel.util.Asserts;
import org.zhiqim.kernel.util.Validates;

/**
 * 服务处理器，对应 /service/* 的地址 
 *
 * @version v1.0.0 @author zhichenggang 2017-1-6 新建与整理
 */
public class ServiceExecutor implements HttpExecutor, ZmlContextConstants
{
    private HttpContext context;
    private HashMap<String, HttpExecutor> executorMap = new HashMap<>();
    private ArrayList<HttpExecutor> executors = new ArrayList<>();
    
    public ServiceExecutor(HttpContext context)
    {
        this.context = context;
        
        //5个精确定位
        executorMap.put(_PATH_SERVICE_AJAX_,        new AjaxService());
        executorMap.put(_PATH_SERVICE_RMI_,         new RmiService());
        executorMap.put(_PATH_SERVICE_VCODE_,       new VcodeService());
        executorMap.put(_PATH_SERVICE_UPLOAD_,      new UploadService(context));
        executorMap.put(_PATH_SERVICE_WS_,          new WebSocketService());
    }
    
    @Override
    public boolean isMatch(String pathInContext)
    {
        return Validates.isMatch(pathInContext, _PATH_SERVICE_);
    }

    @Override
    public void handle(HttpRequest request, HttpResponse response) throws IOException
    {
        HttpExecutor executor = getSerivce(request.getPathInContext());
        if (executor != null)
            executor.handle(request, response);
        else
            request.getContext().getNotFoundHandler().handle(request, response);
    }
    
    public void addService(String path, HttpExecutor service)
    {
        Asserts.as(Validates.isLen(path, 10, 100) && path.startsWith("/service/")?null:"增加ZML上下文环境下服务时，path必须以/service/开头，最长100字符");
        Asserts.as(service != null?null:"增加ZML上下文环境下服务时，服务不能为null");
        
        if (path.contains("*"))
            executors.add(service);
        else
            executorMap.put(path, service);
    }

    /** 查找匹配上的服务 */
    public HttpExecutor getSerivce(String pathInContext)
    {
        //1.先精确
        HttpExecutor executor = executorMap.get(pathInContext);
        if (executor != null)
            return executor;
        
        //2.后模糊
        for (HttpExecutor handler : executors)
        {
            if (handler.isMatch(pathInContext))
                return handler;
        }

        return null;
    }
    
    /***********************************************************************************/
    //获取创建后的服务对象
    /***********************************************************************************/
    
    /** 获取上下文环境 */
    public HttpContext getContext()
    {
        return context;
    }
    
    /** 获取AJAX服务处理器 */
    public AjaxService getAjaxService()
    {
        return (AjaxService)executorMap.get(_PATH_SERVICE_AJAX_);
    }
    
    /** 获取RMI服务处理器 */
    public RmiService getRmiService()
    {
        return (RmiService)executorMap.get(_PATH_SERVICE_RMI_);
    }
    
    /** 获取验证码服务处理器 */
    public VcodeService getVcodeService()
    {
        return (VcodeService)executorMap.get(_PATH_SERVICE_VCODE_);
    }
    
    /** 获取上传服务处理器 */
    public UploadService getUploadService()
    {
        return (UploadService)executorMap.get(_PATH_SERVICE_UPLOAD_);
    }
    
    /** 获取WebSocket服务处理器 */
    public WebSocketService getWebSocketService()
    {
        return (WebSocketService)executorMap.get(_PATH_SERVICE_WS_);
    }
}
